//
// RequestPackage.h
// Usage: Device driver request package
// CreateDate: 2009-06-03
// Author: MaJiuyue
//
#ifndef _REQUEST_PACKAGE_H_
#define _REQUEST_PACKAGE_H_

#include <NewLife.h>
#include <sys/types.h>

enum IRP_TYPE { IRP_DUMMY, IRP_IRQ, IRP_SHUTDOWN, IRP_OPEN, IRP_CLOSE, IRP_READ, IRP_WRITE, IRP_COUNT };

class RequestPackage
{
private:
	IRP_TYPE type;
	pid_t RequestPID;
	u32 p1, p2, p3, p4;

public:
	/* Construct a request package, used by kernel */
	RequestPackage() : type(IRP_DUMMY), p1(0), p2(0), p3(0), p4(0) {}

	/* Prepare a READ IRP */
	void PrepareReadIRP(pid_t pid, u16 minior, off_t off, addr_t buffer, size_t size)
	{
		this->type = IRP_READ;
		this->RequestPID = pid;
		this->p1 = minior;
		this->p2 = off;
		this->p3 = buffer;
		this->p4 = size;
	}

	/* Prepare a WRITE IRP */
	void PrepareWriteIRP(pid_t pid, u16 minior, off_t off, addr_t buffer, size_t size)
	{
		this->type = IRP_WRITE;
		this->RequestPID = pid;
		this->p1 = minior;
		this->p2 = off;
		this->p3 = buffer;
		this->p4 = size;
	}

	/* Prepare a IRQ package */
	void PrepareIRQ(int irq)
	{
		this->type = IRP_IRQ;
		this->p1 = irq;
	}

	/* Get information of this request package */
	IRP_TYPE GetRequestType() { return type; }
	pid_t GetRequestPID() { return RequestPID; }
	int GetRequestMinior() { return p1; }
	off_t GetRequestOffset() { return p2; }
	void * GetRequestBuffer() { return (void *)p3; }
	size_t GetRequestSize() { return p4; }
	int GetIRQ() { return p1; }

	/* Finish this IRP, return value in 'ret', destory memory map */
	void FinishRequest(int ret)
	{
		// IRQ package just for notify, no need to finish
		if(type == IRP_IRQ)
			return;

		// Notify kernel, this request package has already finished.
		__asm__ __volatile__(
			"int $0x90"
			::"a"(0x10000005), "b"(this), "c"(ret)
		);
	}
};

#endif

